import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import {
  baseURL,
  contentType,
  debounce,
  rowLockCode,
  invalidCode,
  noPermissionCode,
  requestTimeout,
  successCode,
  tokenName,
  loginInterception,
} from '../config/index';

import { useMessage } from '@/composables/useMessage';

const { success: showSuccess, error: showError } = useMessage();
import { useSnackbar } from '@/composables/useSnackbar';
import { useLoading } from '@/composables/useLoading';
import { router } from '@/router';
import qs from 'qs';
import { isArray } from '@/utils/validate';
import { useAuthStore } from '@/stores/auth';

let loadingInstance: any;

export interface ResponseData<T = any> {
  code: number;
  msg: string;
  data: T;
}

type ContentType = 'application/json;charset=UTF-8' | 'application/x-www-form-urlencoded;charset=UTF-8';

/**
 * 判断当前url是否需要加loading
 */
const needLoading = (config: AxiosRequestConfig): boolean => {
  return debounce.some((item: string) => config.url?.includes(item));
};

/**
 * 处理code异常
 */
const handleCode = (code: number, msg: string) => {
  const authStore = useAuthStore();
  const { showSnackbar } = useSnackbar();

  switch (code) {
    case rowLockCode:
      showError(msg);

      break;
    case invalidCode:

      showError(msg);
      authStore.logout();

      //跳转到401页面

      if (loginInterception) {
        router.push({ path: '/auth/401' });
      }
      break;
    case noPermissionCode:
      authStore.logout();
      if (loginInterception) {
        router.push({ path: '/auth/401' });
      }
      break;
    default:
      showError(msg);

      break;
  }
};

const instance = axios.create({
  baseURL,
  timeout: requestTimeout,
  withCredentials: false,
  headers: {
    'Content-Type': contentType,
  },
});

instance.interceptors.request.use(
  (config) => {
    const authStore = useAuthStore();
    if (authStore.accessToken) {
      config.headers[tokenName] = authStore.accessToken;
    }

    if ((contentType as ContentType) === 'application/x-www-form-urlencoded;charset=UTF-8' && config.data) {
      config.data = qs.stringify(config.data);
    }

    if (needLoading(config)) {
      const { showLoading } = useLoading();
      loadingInstance = showLoading();
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  (response: AxiosResponse) => {
    if (loadingInstance) loadingInstance.close();

    const { data, config } = response;
    const { code, msg } = data;
    const codeVerificationArray = isArray(successCode) ? [...successCode] : [...[successCode]];

    if (codeVerificationArray.includes(code)) {
      return response.data;
    } else {
      handleCode(code, msg);
      return Promise.reject(
        msg || 'Error'
      );
    }
  },
  (error) => {
    if (loadingInstance) loadingInstance.close();
    const { message } = error;
    let msg = '';
    if (message === 'Network Error') {
      msg = '后端接口连接异常';
    }
    if (message.includes('timeout')) {
      msg = '后端接口请求超时';
    }
    if (message.includes('Request failed with status code')) {
      const code = message.substr(message.length - 3);
      msg = '后端接口' + code + '异常';
    }
    showError(msg);
    return Promise.reject(error);
  }
);

interface AjaxOptions {
  url: string;
  type?: string;
  method?: string;
  async?: boolean;
  data?: any;
  success?: (res: string) => void;
  error?: (status: number) => void;
}

/**
 * 原始ajax请求
 */
export function ajax(obj: AjaxOptions) {
  // 指定提交方式的默认值
  obj.type = obj.type || obj.method || 'get';
  // 设置是否异步，默认为true(异步)
  if (obj.async === null || obj.async === undefined) {
    obj.async = true;
  }
  // 设置数据的默认值
  obj.data = obj.data || null;
  let params = _params(obj.data);
  // 在路径后面添加时间戳加随机数防止浏览器缓存
  obj.url += (obj.url.indexOf('?') > -1 ? '&' : '?') + 't=' + (new Date().getTime() + Math.random());
  if (obj.type.toLowerCase() === 'get' && params.length > 0) {
    // 将转换后的data与url进行拼接
    obj.url += '&' + params;
  }
  let xhr = new XMLHttpRequest();

  xhr.open(obj.type, obj.url, obj.async);

  // 设置token
  const authStore = useAuthStore();
  if (authStore.accessToken) {
    xhr.setRequestHeader(tokenName, authStore.accessToken);
  }

  if (obj.type.toLowerCase() === 'post') {
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send(params);
  } else xhr.send(null);

  if (obj.async) {
    // 异步调用
    // 监听响应状态
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) // 响应状态为4，数据加载完毕
        callback();
    };
  } else callback(); // 同步

  function callback() {
    if (xhr.status === 200) {
      obj.success?.(xhr.responseText);
    } else {
      obj.error?.(xhr.status);
    }
  }

  // 将对象序列化，将对象拼接成url字符串
  function _params(data: any) {
    if (data == null) return '';
    let arr = [];
    for (let i in data) {
      arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));
    }
    return arr.join('&');
  }
}

export default instance; 